<template>
  <div class="carousel-manager">
    <!-- 页面标题区域 -->
    <div class="page-header">
      <h2>轮播图管理</h2>
      <el-tag type="info">共 {{ total }} 个轮播图</el-tag>
    </div>

    <div class="content-box">
      <!-- 操作栏 -->
      <el-card class="operation-area" shadow="hover">
        <div class="control-btns">
          <div class="right-btns">
            <el-button type="primary" plain size="medium" @click="handleAdd">
              <i class="el-icon-plus"></i> 新增轮播图
            </el-button>
          </div>
        </div>
      </el-card>

      <!-- 表格区域 -->
      <el-card class="table-card" shadow="hover">
        <el-table :data="carouselList"
                  border
                  v-loading="loading">
          <el-table-column prop="id" label="ID" width="80" align="center" />
          <el-table-column label="图片" width="220" align="center">
            <template #default="scope">
              <img :src="'api' + scope.row.imageUrl" class="preview-image">
            </template>
          </el-table-column>
          <el-table-column prop="title" label="标题" min-width="120" />
          <el-table-column prop="tag" label="标签" width="120" />
          <el-table-column prop="description" label="描述" min-width="150" show-overflow-tooltip />
          <el-table-column prop="sortOrder" label="排序" width="80" align="center" />
          <el-table-column prop="status" label="状态" width="100" align="center">
            <template #default="scope">
              <el-tag :type="scope.row.status ? 'success' : 'info'">
                {{ scope.row.status ? '启用' : '禁用' }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="180" align="center" fixed="right">
            <template #default="scope">
              <el-button size="mini" type="primary" plain @click="handleEdit(scope.row)">
                <i class="el-icon-edit"></i> 编辑
              </el-button>
              <el-button size="mini" type="danger" plain @click="handleDelete(scope.row)">
                <i class="el-icon-delete"></i> 删除
              </el-button>
            </template>
          </el-table-column>
        </el-table>

        <!-- 分页 -->
        <pagination v-show="total > 0"
                    :total="total"
                    :page.sync="queryParams.currentPage"
                    :limit.sync="queryParams.size"
                    @pagination="getList" />
      </el-card>

      <!-- 新增/编辑弹窗 -->
      <el-dialog :title="dialogTitle"
                 v-model="dialogVisible"
                 width="700px"
                 :close-on-click-modal="false">
        <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
          <el-form-item label="图片" prop="imageUrl">
            <el-upload class="carousel-uploader"
                       action="#"
                       :show-file-list="false"
                       :auto-upload="false"
                       :on-change="handleUpload">
              <img v-if="form.imageUrl" :src="'api' + form.imageUrl" class="carousel-image">
              <div v-else class="carousel-uploader-placeholder">
                <i class="el-icon-plus"></i>
                <div class="placeholder-text">点击上传图片</div>
              </div>
            </el-upload>
            <div class="upload-tip">建议尺寸：900×300px，支持 jpg、png 格式，大小不超过 10MB</div>
          </el-form-item>
          <el-form-item label="标题" prop="title">
            <el-input v-model="form.title" placeholder="请输入标题" />
          </el-form-item>
          <el-form-item label="标签" prop="tag">
            <el-input v-model="form.tag" placeholder="请输入标签" />
          </el-form-item>
          <el-form-item label="描述" prop="description">
            <el-input type="textarea"
                      v-model="form.description"
                      :autosize="{ minRows: 3, maxRows: 5 }"
                      placeholder="请输入描述" />
          </el-form-item>
          <el-form-item label="关联商品" prop="productId">
            <el-select v-model="form.productId"
                       filterable
                       clearable
                       placeholder="请选择商品"
                       style="width: 100%;">
              <el-option label="不关联商品" :value="null"></el-option>
              <el-option v-for="item in productList"
                         :key="item.id"
                         :label="item.name"
                         :value="item.id">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="排序" prop="sortOrder">
            <el-input-number v-model="form.sortOrder"
                             :min="0"
                             controls-position="right"
                             style="width: 120px;" />
          </el-form-item>
          <el-form-item label="状态" prop="status">
            <el-switch v-model="form.status"
                       :active-value="1"
                       :inactive-value="0">
            </el-switch>
          </el-form-item>
        </el-form>
        <template #footer>
          <el-button @click="dialogVisible = false" plain>取 消</el-button>
          <el-button type="primary" @click="submitForm" :loading="submitLoading" plain>确 定</el-button>
        </template>
      </el-dialog>

      <!-- 图片裁剪弹窗 - 重新设计的裁剪模块 -->
      <el-dialog title="图片裁剪"
                 v-model="cropperVisible"
                 width="900px"
                 append-to-body
                 :close-on-click-modal="false"
                 class="cropper-dialog">
        <!-- 裁剪区域和预览区域布局 -->
        <div class="cropper-container">
          <!-- 主裁剪区域 -->
          <div class="main-cropper-area">
            <div class="cropper-wrapper">
              <VueCropper ref="cropper"
                          :img="cropImage"
                          :info="true"
                          :info-true="true"
                          :autoCrop="true"
                          :autoCropWidth="900"
                          :autoCropHeight="300"
                          :fixedBox="true"
                          :fixed="true"
                          :fixedNumber="[3, 1]"
                          :centerBox="true"
                          :high="true"
                          :zoomOnWheel="true"
                          :zoomOnTouch="true"
                          :canMove="true"
                          :canMoveBox="true"
                          :original="false"
                          outputType="png"
                          :enable="true"
                          @realTime="onCropChange">
              </VueCropper>

              <!-- 裁剪操作提示 -->
              <div class="cropper-hint">
                <p>拖动裁剪框或图片调整裁剪区域</p>
                <p>鼠标滚轮或双指缩放图片</p>
              </div>
            </div>

            <!-- 裁剪控制按钮 -->
            <div class="cropper-controls">
              <el-button size="small" @click="resetCrop" plain>
                <i class="el-icon-refresh"></i> 重置
              </el-button>
              <el-button size="small" @click="rotateLeft" plain>
                <i class="el-icon-refresh-left"></i> 向左旋转
              </el-button>
              <el-button size="small" @click="rotateRight" plain>
                <i class="el-icon-refresh-right"></i> 向右旋转
              </el-button>
              <el-slider
                  v-model="scale"
                  :min="0.1"
                  :max="2"
                  :step="0.1"
                  @change="setScale"
                  class="zoom-slider"
                  tooltip="always">
              </el-slider>
            </div>
          </div>

          <!-- 预览区域 -->
          <div class="preview-area">
            <h4>裁剪预览 (900×300px)</h4>
            <div class="preview-container">
              <div class="preview-wrapper">
                <img :src="previewImage" class="preview-img">
              </div>
              <div class="preview-info">
                <p>最终尺寸: 900 × 300 像素</p>
                <p>比例: 3:1 (宽:高)</p>
              </div>
            </div>
          </div>
        </div>

        <template #footer>
          <el-button @click="cropperVisible = false" plain>取 消</el-button>
          <el-button type="primary" @click="handleCropUpload" :loading="uploadLoading" plain>确 定</el-button>
        </template>
      </el-dialog>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, getCurrentInstance, watch } from 'vue'
import Request from '../utils/request.js'
import Pagination from '../components/Pagination/index.vue'
import { VueCropper } from 'vue-cropper'
import { inject } from 'vue'
import { ElMessage, ElConfirm } from 'element-plus' // 引入Element Plus组件

// 注入用户信息
const userInfo = inject('userInfo')

// 消息提示
const showMessage = (message, type = 'info') => {
  ElMessage({
    message,
    type,
    duration: 3000
  })
}

// 查询参数
const queryParams = reactive({
  currentPage: 1,
  size: 10
})

// 数据存储
const total = ref(0)
const carouselList = ref([])
const productList = ref([])

// 对话框状态
const dialogVisible = ref(false)
const dialogTitle = ref('')
const cropperVisible = ref(false)

// 表单数据
const form = reactive({
  id: undefined,
  imageUrl: '',
  title: '',
  tag: '',
  description: '',
  productId: null,
  sortOrder: 0,
  status: 1
})

// 裁剪相关
const cropImage = ref('')
const uploadFile = ref(null)
const cropper = ref(null)
const previewImage = ref('')
const scale = ref(1) // 缩放比例

// 验证规则
const rules = ref({
  imageUrl: [{ required: true, message: '请上传图片', trigger: 'change' }],
  title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
})

// 加载状态
const loading = ref(false)
const submitLoading = ref(false)
const uploadLoading = ref(false)

// 表单引用
const formRef = ref(null)

// 页面加载时初始化数据
onMounted(() => {
  getList()
  getProducts()
})

// 获取轮播图列表
const getList = async () => {
  try {
    loading.value = true
    const res = await Request.get('/carousel/page', {
      params: queryParams
    })
    if (res.code === '0') {
      carouselList.value = res.data.records
      total.value = res.data.total
    }
  } catch (error) {
    console.error('获取轮播图列表失败:', error)
    showMessage('获取轮播图列表失败', 'error')
  } finally {
    loading.value = false
  }
}

// 获取商品列表
const getProducts = async () => {
  try {
    const res = await Request.get('/product/all')
    if (res.code === '0') {
      productList.value = res.data
    }
  } catch (error) {
    console.error('获取商品列表失败:', error)
    showMessage('获取商品列表失败', 'error')
  }
}

// 处理新增
const handleAdd = () => {
  dialogTitle.value = '新增轮播图'
  Object.assign(form, {
    id: undefined,
    imageUrl: '',
    title: '',
    tag: '',
    description: '',
    productId: null,
    sortOrder: 0,
    status: 1
  })
  dialogVisible.value = true
}

// 处理编辑
const handleEdit = (row) => {
  dialogTitle.value = '编辑轮播图'
  Object.assign(form, row)
  dialogVisible.value = true
}

// 处理删除
const handleDelete = async (row) => {
  try {
    ElConfirm({
      message: '确认删除该轮播图?',
      confirmButtonText: '确认',
      cancelButtonText: '取消',
      type: 'warning',
    }).then(async () => {
      try {
        const res = await Request.delete(`/carousel/${row.id}`)
        if (res.code === '0') {
          showMessage('删除成功', 'success')
          getList()
        } else {
          showMessage(res.msg || '删除失败', 'error')
        }
      } catch (error) {
        console.error('删除轮播图失败:', error)
        showMessage('删除轮播图失败', 'error')
      }
    }).catch(() => {
      // 取消删除
    })
  } catch (error) {
    console.error('删除轮播图失败:', error)
    showMessage('删除轮播图失败', 'error')
  }
}

// 处理图片上传
const handleUpload = (file) => {
  // 检查文件类型和大小
  const isImage = file.raw.type.startsWith('image/')
  const isLt10M = file.raw.size / 1024 / 1024 < 10

  if (!isImage) {
    showMessage('上传文件只能是图片格式!', 'error')
    return
  }
  if (!isLt10M) {
    showMessage('上传图片大小不能超过 10MB!', 'error')
    return
  }

  // 保存原始文件
  uploadFile.value = file.raw
  // 读取文件并显示裁剪框
  const reader = new FileReader()
  reader.onload = (e) => {
    cropImage.value = e.target.result
    previewImage.value = '' // 重置预览
    scale.value = 1 // 重置缩放
    cropperVisible.value = true
  }
  reader.readAsDataURL(file.raw)
}

// 裁剪实时更新预览
const onCropChange = (data) => {
  if (cropper.value) {
    cropper.value.getCropData((data) => {
      previewImage.value = data
    })
  }
}

// 重置裁剪
const resetCrop = () => {
  if (cropper.value) {
    cropper.value.reset()
    scale.value = 1
  }
}

// 向左旋转
const rotateLeft = () => {
  if (cropper.value) {
    cropper.value.rotateLeft()
  }
}

// 向右旋转
const rotateRight = () => {
  if (cropper.value) {
    cropper.value.rotateRight()
  }
}

// 设置缩放
const setScale = (value) => {
  if (cropper.value) {
    cropper.value.zoomTo(value)
  }
}

// 处理裁剪上传
const handleCropUpload = async () => {
  try {
    uploadLoading.value = true

    if (!cropper.value) {
      throw new Error('裁剪组件未初始化')
    }

    // 获取裁剪后的图片数据
    const { getCropBlob } = cropper.value
    getCropBlob(async (blob) => {
      try {
        // 创建文件名
        const fileName = uploadFile.value?.name || 'carousel-image.png'

        // 创建 File 对象
        const file = new File([blob], fileName, { type: 'image/png' })

        // 创建 FormData
        const formData = new FormData()
        formData.append('file', file)

        // 发送上传请求
        const res = await Request.post('/file/upload/img', formData, {
          headers: {
            'Content-Type': 'multipart/form-data',
            'token': userInfo?.token || ''
          }
        })

        if (res.code === '0') {
          form.imageUrl = res.data
          showMessage('上传成功', 'success')
          cropperVisible.value = false
        } else {
          showMessage(res.msg || '上传失败', 'error')
        }
      } catch (error) {
        console.error('上传失败:', error)
        showMessage('上传失败', 'error')
      } finally {
        uploadLoading.value = false
      }
    })
  } catch (error) {
    console.error('裁剪失败:', error)
    showMessage('裁剪失败: ' + error.message, 'error')
    uploadLoading.value = false
  }
}

// 提交表单
const submitForm = async () => {
  try {
    const valid = await formRef.value.validate()
    if (valid) {
      submitLoading.value = true
      const method = form.id ? 'put' : 'post'
      const url = form.id ? `/carousel/${form.id}` : '/carousel'
      const res = await Request[method](url, { ...form })

      if (res.code === '0') {
        showMessage(`${form.id ? '更新' : '新增'}成功`, 'success')
        dialogVisible.value = false
        getList()
      } else {
        showMessage(res.msg || `${form.id ? '更新' : '新增'}失败`, 'error')
      }
    }
  } catch (error) {
    if (error.name !== 'ValidationError') {
      console.error('保存轮播图失败:', error)
      showMessage('操作失败', 'error')
    }
  } finally {
    submitLoading.value = false
  }
}
</script>

<style lang="less" scoped>
.carousel-manager {
  padding: 24px;
  background-color: #f0f2f5;
  min-height: calc(100vh - 60px);
}

.page-header {
  display: flex;
  align-items: center;
  margin-bottom: 24px;

  h2 {
    font-size: 24px;
    font-weight: 500;
    color: #1f2f3d;
    margin: 0;
    margin-right: 15px;
  }
}

.operation-area {
  background: white;
  border-radius: 8px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
  margin-bottom: 24px;
}

.table-card {
  border-radius: 8px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
}

.control-btns {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px;

  .right-btns {
    display: flex;
    gap: 10px;
  }
}

.preview-image {
  height: 60px;
  width: 180px;
  border-radius: 4px;
  object-fit: contain;
  background-color: #f5f7fa;
}

.carousel-uploader {
  border: 1px dashed #d9d9d9;
  border-radius: 8px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  width: 450px;
  height: 150px;
  display: flex;
  justify-content: center;
  align-items: center;

  &:hover {
    border-color: #409EFF;
  }

  .carousel-image {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: contain;
    background-color: #f5f7fa;
  }

  .carousel-uploader-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    color: #8c939d;
    background-color: #f5f7fa;

    .el-icon-plus {
      font-size: 28px;
      margin-bottom: 8px;
      color: #c0c4cc;
    }

    .placeholder-text {
      font-size: 14px;
      color: #909399;
    }
  }
}

.upload-tip {
  font-size: 12px;
  color: #909399;
  margin-top: 8px;
}

/* 重新设计的裁剪模块样式 */
.cropper-dialog {
  .el-dialog__body {
    padding: 0;
    overflow: hidden;
  }
}

.cropper-container {
  display: flex;
  flex-direction: column;
  height: 600px;
  padding: 20px;
  box-sizing: border-box;
}

.main-cropper-area {
  flex: 1;
  display: flex;
  flex-direction: column;
  margin-bottom: 20px;
}

.cropper-wrapper {
  flex: 1;
  position: relative;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  overflow: hidden;
  background-color: #f9fafb;
}

/* 裁剪提示信息 */
.cropper-hint {
  position: absolute;
  bottom: 10px;
  left: 0;
  right: 0;
  text-align: center;
  font-size: 12px;
  color: #666;
  background-color: rgba(255, 255, 255, 0.8);
  padding: 5px;
  border-radius: 4px;
  margin: 0 10px;

  p {
    margin: 3px 0;
  }
}

/* 裁剪控制按钮 */
.cropper-controls {
  display: flex;
  align-items: center;
  padding: 10px;
  gap: 10px;
  background-color: #f5f7fa;
  border-radius: 6px;
  margin-top: 10px;

  .zoom-slider {
    flex: 1;
    margin: 0 10px;
  }
}

/* 预览区域 */
.preview-area {
  padding: 15px;
  background-color: #f5f7fa;
  border-radius: 6px;

  h4 {
    margin: 0 0 15px 0;
    font-size: 14px;
    color: #333;
  }
}

.preview-container {
  display: flex;
  align-items: center;
  gap: 20px;
}

.preview-wrapper {
  width: 300px;
  height: 100px;
  overflow: hidden;
  border: 1px solid #ddd;
  border-radius: 4px;
  background-color: white;
}

.preview-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.preview-info {
  font-size: 12px;
  color: #666;

  p {
    margin: 5px 0;
  }
}

/* 解决被动事件监听器警告的样式 */
:deep(.cropper-container) {
  touch-action: manipulation !important;
}

:deep(.cropper-container img) {
  touch-action: manipulation !important;
}

:deep(.el-upload) {
  touch-action: manipulation !important;
}

/* 裁剪框样式优化 */
:deep(.cropper-crop-box) {
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.5);
  border: 1px dashed #409EFF;
}

:deep(.cropper-view-box) {
  outline: 1px solid #409EFF;
}
</style>
